#pragma once
#include <algorithm>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>

#include "bondlib.h"

using namespace std;

class S_BONDLIB_EXPORT CBondType {
 public:
  CBondType();
  CBondType(const char* sCode, const char* sName, const char* sNameEn);
  virtual ~CBondType();

 public:
  void Clear();
  bool operator==(const CBondType& one);

  int GetSize();
  void AddSubType(CBondType& subType);
  std::vector<CBondType>* GetBondSubTypeList();
  CBondType* GetBondSubType(const char* szSubBondCode);

 public:
  std::string m_Code;
  std::string m_Name_C;
  std::string m_Name_E;

 protected:
  std::vector<CBondType> m_list;
};

class S_BONDLIB_EXPORT CBondTypeList {
 public:
  static CBondTypeList& instance();

 public:
  CBondTypeList();
  virtual ~CBondTypeList();

 public:
  int GetSize();
  std::vector<CBondType>* GetBondTypeList();
  CBondType* GetBondSubTypeList(const char* strNameC);
  CBondType* GetBondSubType(const char* szSubBondCode);

 protected:
  std::vector<CBondType> m_list;
};

class S_BONDLIB_EXPORT CBondTypeV2 {
 public:
  CBondTypeV2();
  CBondTypeV2(const char* pszEnName, const char* pszCnName);
  virtual ~CBondTypeV2();

  typedef std::unordered_map<std::string, CBondType> UMAP_SUBTYPE;

 public:
  void Clear();
  unsigned int Size();
  void Add(CBondType& subType);
  void Add(CBondType subType);
  const UMAP_SUBTYPE& GetMap();
  const CBondType& GetSubType(const char* szSubTypeCode);

 public:
  std::string m_Name_C;
  std::string m_Name_E;

 protected:
  UMAP_SUBTYPE m_umapSubType;
};

class S_BONDLIB_EXPORT CBondTypeMap {
 public:
  static CBondTypeMap instance();
  virtual ~CBondTypeMap();

  typedef std::unordered_map<unsigned int, CBondTypeV2> UMAP_TYPE2BODY;
  typedef std::unordered_map<std::string, unsigned int> UMAP_CODE2TYPE;

 public:
  unsigned int Size();
  const UMAP_TYPE2BODY& GetMap();

  const CBondTypeV2& GetType(unsigned int nCode);

  const CBondTypeV2& GetType(const char* pszSubType,
                             const char* pszEntCor = NULL);

  unsigned int GetTypeEm(const char* pszSubType, const char* pszEntCor = NULL);

 protected:
  CBondTypeMap();

  UMAP_TYPE2BODY m_umapType2Body;
  UMAP_CODE2TYPE m_umapCode2Type;
};
